#include <stdio.h>
#include <stdlib.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include "descriptors.h"

// funcao calcula gaussiana e gaussiana da gaussiana para tirar a diferenca
void* DoG(IplImage *img2, double **COM1A, double *HD1, double *HD2, int nColor){

	IplImage *imgGau1, *imgGau2, *imgGauResult, *imgLM, *imgaux, *Ixy;
	//cria imagens	
	imgGau1 = cvCreateImage(cvGetSize(img2),IPL_DEPTH_8U,1);
	imgGau2 = cvCreateImage(cvGetSize(img2),IPL_DEPTH_8U,1);
	imgGauResult = cvCreateImage(cvGetSize(img2),IPL_DEPTH_8U,1);
	imgLM = cvCreateImage(cvGetSize(img2),IPL_DEPTH_8U,1);
	
	// passa filtro na direcao x e y
	Ixy = cvCreateImage(cvGetSize(img2),IPL_DEPTH_8U,1);
	imgaux = cvCreateImage(cvGetSize(img2),IPL_DEPTH_16S,1);
	cvSobel(img2, imgaux, 1, 1, 3);	
	cvConvertScaleAbs( imgaux , Ixy, 1, 0);
	cvReleaseImage(&imgaux);

	// cria ponteiros
	uchar *dataimg2 = (uchar *)img2->imageData;
	uchar *data1 = (uchar *)imgGau1->imageData;
	uchar *data2 = (uchar *)imgGau2->imageData;
	uchar *datar = (uchar *)imgGauResult->imageData;
	uchar *dataLM = (uchar *)imgLM->imageData;
	
	// cria um quadrado para passar na DoG para achar os locais maximos
	// neste caso o quadrado teria que ter 0 no centro -> 1 1 1, mas nao sei como faz isso xD
	//						      1 0 1
	//						      1 1 1	
	IplConvKernel *stelem_r = cvCreateStructuringElementEx(5,5, 1,1, CV_SHAPE_ELLIPSE, NULL);//quadrado;
 	int step = img2->widthStep;
	int i, j, xy = 0, x, y, indice;
	int vectX[200], vectY[200];

	cvSmooth( Ixy, imgGau1, CV_GAUSSIAN, 5, 5, 1.4, 0);// gaussiana
	cvSmooth( imgGau1, imgGau2, CV_GAUSSIAN, 5, 5, 1.4, 0);// gaussiana da gaussiana
 
 	// percorre a imagem para calcular a DoG
 	for (i = 0; i < img2->height; i++) {
      		for (j = 0; j < img2->width; j++) {
	  		datar[i*step+j] = data2[i*step+j] - data1[i*step+j]; //diferen'ca da gaussiana
      		}
 	}
	// atraves da erosao eh possivel achar os locais maximos
	cvErode(imgGauResult, imgLM, stelem_r, 1);
	//cvDilate

	// percorre a imagem achar as possicoes dos locais maximos
 	for (i = 128; i < img2->height-128; i=i+3) {
      		for (j = 128; j < img2->width-128; j=j+3) {
	  		 if (dataLM[i*step+j] > 245 ){
			 	vectX[xy] = i;
				vectY[xy] = j;
				xy++;				
			 }				
      		}
 	}

	double minDistH = DBL_MAX;
	// calculo haralick de cada local maximo	
	for(xy = 0; xy<200; xy++){
		x = vectX[xy] - 64;
		y = vectY[xy] - 64;
		// matriz de coocorrencia e haralick
		CoocurrenceMatrix(img2, COM1A, nColor, 1, 0, x, y);
		Haralick(COM1A, nColor, HD2);

		// compara os descritores
		// Haralick - tamanho do descritor = 6
		double distH[200];
		distH[xy] = distManhattan(HD1, HD2, 6);
		  // encontra distancia minima
		  if (distH[xy] < minDistH) {
		      minDistH = distH[xy];
			indice = xy;
		  }
	}
	// marca na imagem o objeto encontrado.
	for (i = vectX[xy] - 64; i < vectX[xy] + 64; i++){
		dataimg2[i*step+j] = 255;
		dataimg2[(i+128)*step+j] = 255;
	}
	for (j = vectY[xy] - 64; j < vectY[xy] + 64; j++){
		dataimg2[i*step+j] = 255;
		dataimg2[i*step+j+128] = 255;
	}
	
	

	printf("xy = %d\n", xy);
	
	cvNamedWindow("Imagem_Consulta", CV_WINDOW_AUTOSIZE);
  	cvShowImage("Imagem_Consulta", Ixy);
  	cvNamedWindow("1", CV_WINDOW_AUTOSIZE);
  	cvShowImage("1", imgGau1);
  	cvNamedWindow("2", CV_WINDOW_AUTOSIZE);
  	cvShowImage("2", imgGau2);
	cvNamedWindow("R", CV_WINDOW_AUTOSIZE);
  	cvShowImage("R", imgGauResult);
	cvNamedWindow("LM", CV_WINDOW_AUTOSIZE);
  	cvShowImage("LM", imgLM);
}
	
int main (int argc, char *argv[]) {
    
    	IplImage *img1, *img2, *imgRg;
	const char *file1, *file2;
    	int nColor = 128; // numero de cores para quantizar a imagem
    	int i, j;
	file1 = argv[1]; //file2 = argv[2];
	FILE *f= fopen("arquivo.txt", "r");
	char c;
  	char linha[5];

     	//carega a imagem sem alterar o sistema de cores
    	img1 = cvLoadImage(file1, IPL_DEPTH_8U);
      	if (!img1) {
	  fprintf(stdout,"Nao foi possivel carregar imagem de entrada\n\n");
	  fflush(stdout);
	  return -1;
      	}
	
	// matriz de coocorrencia
    	double **COM1A = (double **)calloc(nColor, sizeof(double*));
    	for (i=0; i<nColor; i++) {
		  COM1A[i]= (double *)calloc(nColor, sizeof(double));
    	}    

    	// Haralick Descriptors
    	double *HD1 = (double *)calloc(6, sizeof(double));
    	double *HD2 = (double *)calloc(6, sizeof(double));
  
    	//calcula matriz de coocorrencia e descritores de Haralick
    	//da imagem de consulta
    	// imagem, matriz, quantizacao, Q = (1,0) e Q = (0,1)
    	//CoocurrenceMatrix(img1, COM1A, nColor, 1, 0, 0, 0);
    	//Haralick(COM1A, nColor, HD1);
        
    	for(i=0; i<7; i++){
		for(j=0;j<5;j++){
			c = getc(f);
			linha[j] = c;
		}
		  // carrega a imagem do banco de imagens
		  img2 = cvLoadImage(linha, CV_LOAD_IMAGE_UNCHANGED);  //
   		  // verifica se conseguiu abrir arquivo 2
   		  if (!img2) {
			printf("Cound not open image file 2\n");
   		  }
	cvNamedWindow("Imagem_Consulta", CV_WINDOW_AUTOSIZE);
  	cvShowImage("Imagem_Consulta", img2);
	cvWaitKey(0);

		// funcao que calcula gaussiana1 e gaussiana da gaussiana para a subtracao
		DoG(img2, COM1A, HD1, HD2, nColor);

    	}	  	
  	  
	// abre uma janela para exibir imagem
	  fclose(f);
  	  cvWaitKey(0);
  	  return 0;
}	
